package com.xiaoma.common.extend

import android.os.Looper
import android.util.Log
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicReference
import kotlin.coroutines.AbstractCoroutineContextElement
import kotlin.coroutines.CoroutineContext

/**
 * author: liangjingbo
 * date: 2022/11/15
 * describe:
 */
private val scopeRef: AtomicReference<Any> = AtomicReference()

val appGlobalScope: CoroutineScope
    get() {
        while (true) {
            val existing = scopeRef.get() as CoroutineScope?
            if (existing != null) {
                return existing
            }
            val newScope = SafeCoroutineScope()
            if (scopeRef.compareAndSet(null, newScope)) {
                return newScope
            }
        }
    }

private class SafeCoroutineScope : CoroutineScope {
    override val coroutineContext: CoroutineContext
        get() = SupervisorJob() + Dispatchers.Main.immediate + XMCoroutineExceptionHandler()
}


private class XMCoroutineExceptionHandler :
    AbstractCoroutineContextElement(CoroutineExceptionHandler),
    CoroutineExceptionHandler {
    override fun handleException(context: CoroutineContext, exception: Throwable) {
        // nothing to do
        Log.i("XMCoroutineExceptionHandler_XMTag", "handleException() Throwable: $exception")
    }
}
val isOnMainThread: Boolean
    get() = Looper.myLooper() == Looper.getMainLooper()
fun runOnMainThread(block: () -> Unit) {
    if (isOnMainThread) block.invoke()
    else appGlobalScope.launch(Dispatchers.Main) { block.invoke() }
}